using System.Linq;
using Microsoft.EntityFrameworkCore;
using UwinEducation.Domain.Entities;
using UwinEducation.Domain.IRepositories;
using UwinEducation.Infrastructure.Persistence;
using UwinEducation.Shared.Enums;
using UwinEducation.Shared.Models;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace UwinEducation.Infrastructure.Repositories
{
    /// <summary>
    /// 教师课表仓储实现
    /// </summary>
    public class TeacherScheduleRepository
        : Repository<TeacherSchedule, Guid>,
            ITeacherScheduleRepository
    {
        public TeacherScheduleRepository(ApplicationDbContext context)
            : base(context) { }

        public async Task<PagedResult<TeacherSchedule>> GetPagedListAsync(
            TeacherSchedulePageRequest pageRequest
        )
        {
            var query = _context
                .TeacherSchedules.AsNoTracking()
                .Include(ts => ts.Teacher)
                .Include(ts => ts.Course)
                .Include(ts => ts.Classroom)
                .Include(ts => ts.TeacherScheduleDetails)
                .AsQueryable();

            if (pageRequest.TeacherId.HasValue)
            {
                query = query.Where(ts => ts.TeacherId == pageRequest.TeacherId);
            }
            if (pageRequest.GroupId.HasValue)
            {
                query = query.Where(ts => ts.GroupId == pageRequest.GroupId);
            }
            if (pageRequest.CourseId.HasValue)
            {
                query = query.Where(ts => ts.CourseId == pageRequest.CourseId);
            }
            if (pageRequest.StartDate.HasValue)
            {
                query = query.Where(ts => ts.StartTime.Date >= pageRequest.StartDate.Value.Date);
            }
            //TODO 时间过滤为实现
            if (pageRequest.EndDate.HasValue)
            {
                query = query.Where(ts => ts.EndTime.Date <= pageRequest.EndDate.Value.Date);
            }
            if (!string.IsNullOrEmpty(pageRequest.Remarks))
            {
                query = query.Where(ts => ts.Remarks.Contains(pageRequest.Remarks));
            }

            var total = await query.CountAsync();
            var items = await query
                .OrderBy(ts => ts.StartTime)
                .Skip((pageRequest.PageIndex - 1) * pageRequest.PageSize)
                .Take(pageRequest.PageSize)
                .ToListAsync();

            return new PagedResult<TeacherSchedule> { Total = total, Items = items };
        }

        public override async Task<TeacherSchedule> GetByIdAsync(Guid id)
        {
            var teacherSchedule = await _context
                .TeacherSchedules.AsNoTracking()
                .Include(ts => ts.Teacher)
                .Include(ts => ts.Course)
                .Include(ts => ts.Classroom)
                .Include(ts => ts.TeacherScheduleDetails)
                .FirstOrDefaultAsync(ts => ts.Id == id);

            return teacherSchedule;

            //return await _context
            //    .TeacherSchedules.Include(ts => ts.Teacher)
            //    .Include(ts => ts.Course)
            //    .Include(ts => ts.Classroom)
            //    .FirstOrDefaultAsync(ts => ts.Id == id);
        }

        public async Task<List<TeacherSchedule>> GetByTeacherIdAsync(Guid teacherId)
        {
            return await _context
                .TeacherSchedules.AsNoTracking()
                .Include(ts => ts.Teacher)
                .Include(ts => ts.Course)
                .Include(ts => ts.Classroom)
                .Where(ts => ts.TeacherId == teacherId)
                .OrderBy(ts => ts.StartTime)
                .ToListAsync();
        }

        public async Task<List<TeacherSchedule>> GetByCourseIdAsync(Guid courseId)
        {
            return await _context
                .TeacherSchedules.AsNoTracking()
                .Include(ts => ts.Teacher)
                .Include(ts => ts.Classroom)
                .Include(ts => ts.Course)
                .Where(ts => ts.CourseId == courseId)
                .OrderBy(ts => ts.StartTime)
                .ToListAsync();
        }

        public async Task<bool> HasTimeConflictAsync(
            Guid teacherId,
            DateTime startTime,
            DateTime endTime,
            Guid? excludeId = null
        )
        {
            //时间冲突需要到明细表中查询
            var details = _context.TeacherScheduleDetails.Where(td =>
                td.TeacherSchedule.TeacherId == teacherId
            );
            if (details.Any())
            {
                //时间冲突根据时间点匹配
                details = details.Where(ts =>
                    details.Any(td =>
                        (td.StartTime <= startTime && td.EndTime > startTime)
                        || (td.StartTime < endTime && td.EndTime >= endTime)
                        || (td.StartTime >= startTime && td.EndTime <= endTime)
                    )
                );
            }

            if (excludeId.HasValue)
            {
                details = details.Where(ts => ts.Id != excludeId.Value);
            }

            return await details.AnyAsync();
        }

        public async Task AddRangeAsync(List<TeacherSchedule> teacherSchedules)
        {
            await _context.TeacherSchedules.AddRangeAsync(teacherSchedules);
            await _context.SaveChangesAsync();
        }

        public async Task<List<TeacherSchedule>> GetByGroupIdAsync(Guid groupId)
        {
            return await _context.TeacherSchedules.AsNoTracking()
                .Where(ts => ts.GroupId == groupId).ToListAsync();
        }

        public async Task<List<TeacherSchedule>> GetByGroupIdsAsync(List<Guid> groupIds)
        {
            return await _context
                .TeacherSchedules.AsNoTracking()
                .Include(ts => ts.TeacherScheduleDetails)
                .Where(ts => groupIds.Contains(ts.GroupId))
                .ToListAsync();
        }

        /// <summary>
        /// 获取教师课表统计分页列表
        /// </summary>
        public async Task<PagedResult<TeacherSchedule>> GetStatisticsPagedListAsync(
            TeacherScheduleStatisticsPageRequest pageRequest
        )
        {
            var query = BaseQuery().AsNoTracking()
                .Include(ts => ts.Teacher)
                .Include(ts => ts.Course)
                .Include(ts => ts.Classroom)
                .Include(ts => ts.TeacherScheduleDetails)
                .AsQueryable();
            query = query.Where(ts =>
                (!pageRequest.TeacherId.HasValue || ts.TeacherId == pageRequest.TeacherId)
                && (!pageRequest.CourseId.HasValue || ts.CourseId == pageRequest.CourseId)
                && (
                    !pageRequest.StartDate.HasValue
                    || ts.StartTime.Date >= pageRequest.StartDate.Value.Date
                )
                && (
                    !pageRequest.EndDate.HasValue
                    || ts.EndTime.Date <= pageRequest.EndDate.Value.Date
                )
            );

            var total = await query.CountAsync();
            var items = await query
                .OrderByDescending(ts => ts.CreatedAt)
                .Skip((pageRequest.PageIndex - 1) * pageRequest.PageSize)
                .Take(pageRequest.PageSize)
                .ToListAsync();

            return new PagedResult<TeacherSchedule> { Total = total, Items = items };
        }

        /// <summary>
        /// 获取教室的课表列表
        /// </summary>
        public async Task<List<TeacherSchedule>> GetByClassroomIdAsync(Guid? classroomId, DateTime startTime, DateTime endTime)
        {
            return await _context.TeacherSchedules.AsNoTracking()
                .Include(x => x.TeacherScheduleDetails)
                .Where(x => x.ClassroomId == classroomId && (startTime <= x.StartTime || endTime >= x.EndTime))
                .ToListAsync();
        }

        /// <summary>
        /// 获取指定日期范围内教师的所有课表
        /// </summary>
        public async Task<List<TeacherSchedule>> GetByTeacherIdInDateRangeAsync(Guid teacherId, DateTime startDate, DateTime endDate)
        {
            return await _context.TeacherSchedules.AsNoTracking()
                .Include(ts => ts.TeacherScheduleDetails)
                .Where(ts => ts.TeacherId == teacherId &&
                     (ts.StartTime.Date <= endDate.Date && ts.EndTime.Date >= startDate.Date))
                .ToListAsync();
        }
    }
}
